package edu.asu.sapa.sas;

import java.util.*;

/**
 * 
 * @author vidar
 * @deprecated
 */
public class CanonicalEffect {
	public static int numEffects = 0;
	protected Variable var; // the variable this effect acts upon
	protected ArrayList<Condition> effectConditionList = new ArrayList<Condition>();
	protected HashMap<Integer, ArrayList<Integer>> effectConditionValues = new HashMap<Integer, ArrayList<Integer>>();

	protected int id;
	
	/** all operators associated with this effect */
	protected ArrayList<SASOperator> operatorList = new ArrayList<SASOperator>();
	
	protected int oldValue = -1; // undefined initially, meaning any value
	protected int newValue = -1;

	public CanonicalEffect(Variable var, int oldValue, int newValue) {
		this.var = var;
		this.oldValue = oldValue;
		this.newValue = newValue;
		id = numEffects++;
	}
	
	public boolean addEffectCondition(Variable var, int val) {
		// goals can have more than one value on the same variable
		ArrayList<Integer> condValueList = effectConditionValues.get(var.getID()); 
		if (condValueList == null) {
			condValueList = new ArrayList<Integer>();
		}
		condValueList.add(val);
		effectConditionValues.put(var.getID(), condValueList); 
		return effectConditionList.add(new Condition(var, val));
	}
	
	public void addEffectConditionList(ArrayList<Condition> effCondList) {
		for (Condition cond : effCondList) {
			addEffectCondition(cond.getVariable(), cond.getValueID());
		}
	}

	public void setNewValue(int nVal) {
		newValue = nVal;
	}
	
	public void setOldValue(int oVal) {
		oldValue = oVal;
	}
	
	public void setVariable(Variable var) {
		this.var = var;
	}
	
	public int getID() {
		return id;
	}
	
	public Variable getVariable() {
		return var;
	}
	
	public int getNewValue() {
		return newValue;
	}
	
	public int getOldValue() {
		return oldValue;
	}

	public boolean addOperator(SASOperator op) {
		return operatorList.add(op);
	}
	
	@Override
	public boolean equals(Object o) {
		if (!(o instanceof CanonicalEffect)) {
			return false;
		} else {
			CanonicalEffect eff = (CanonicalEffect)o;
			
			if (effectConditionList.size() == eff.effectConditionList.size() && 
					eff.newValue == newValue &&
					eff.oldValue == oldValue &&
					eff.var.getID() == var.getID()) {
				return true;
			} else {
				return false;
			}
		}
	}
	
	@Override
	public int hashCode() {
		return (new Integer(newValue)).hashCode() << 16 | 
		       (new Integer(oldValue)).hashCode() << 8 | 
			   (new Integer(var.getID())).hashCode();
	}

	public void compileCondition() {
		int size = effectConditionList.size();
		if (size == 0) return;

		if (size == 1) {
			Condition cond = effectConditionList.get(0);
			if (cond.getVarID() == var.getID() && oldValue == SAS.UNDEFINED) {
				effectConditionList.clear();
				oldValue = cond.getValueID();
			} else {
				throw new RuntimeException("Cannot compile effect condition. Cond Var: " +
						cond.getVarID() + "Eff Var: " + var.getID() + "Old Value: " + oldValue);
			}
		} else {
			throw new RuntimeException("Effect conditions size > 1 (i.e., no derived preds or ADL constructs allowed)");
		}
	}
	
	/** returns non-canonical verion of this effect
	 * @deprecated 
	 */
	public ArrayList<Effect> getEffects() {
		ArrayList<Effect> effects = new ArrayList<Effect>();
		Effect eff;
		// non-canonical effects from this canonical one
		for (SASOperator op : operatorList) {
			eff = new Effect(var, oldValue, newValue);
			eff.setOperator(op);
			effects.add(eff);
		}

		return effects;
	}

	public ArrayList<SASOperator> getOperators() {
		return operatorList;
	}
}
